//
// Created by RandBII on 2020/12/24.
//

#include "ImageDefine.h"

void NativeImageUtil::AllocNativeImage(NativeImage *pImage) {
    if (pImage->width == 0 || pImage->height == 0) return;

    switch (pImage->format) {
        case IMAGE_FORMAT_RGBA:
            pImage->ppPlane[0] = static_cast<uint8_t *>(malloc(pImage->width * pImage->height * 4));
            pImage->pLineSize[0] = pImage->width * 4;
            pImage->pLineSize[1] = 0;
            pImage->pLineSize[2] = 0;
            break;
        case IMAGE_FORMAT_NV12:
        case IMAGE_FORMAT_NV21:

            pImage->ppPlane[0] = static_cast<uint8_t *> (malloc(
                    pImage->width * pImage->height * 1.5));
            pImage->ppPlane[1] = pImage->ppPlane[0] + pImage->width * pImage->height;
            pImage->pLineSize[0] = pImage->width;
            pImage->pLineSize[1] = pImage->width;
            pImage->pLineSize[2] = 0;
            break;
        case IMAGE_FORMAT_I420:

            pImage->ppPlane[0] = static_cast<uint8_t *>(malloc(
                    pImage->width * pImage->height * 1.5));
            pImage->ppPlane[1] = pImage->ppPlane[0] + pImage->width * pImage->height;
            pImage->pLineSize[0] = pImage->width;
            pImage->pLineSize[1] = pImage->width / 2;
            pImage->pLineSize[2] = pImage->width / 2;
            break;
        default:
            LOG_I("NativeImageUtil::AllocNativeImage default");
            break;
    }

}

void NativeImageUtil::FreeNativeImage(NativeImage *pNativeImage) {

    if (pNativeImage == nullptr || pNativeImage->ppPlane[0] == nullptr) return;
    free(pNativeImage->ppPlane[0]);
    pNativeImage->ppPlane[0] = nullptr;
    pNativeImage->ppPlane[1] = nullptr;
    pNativeImage->ppPlane[2] = nullptr;

}

void NativeImageUtil::CopyNativeImage(NativeImage *pSrcImg, NativeImage *pDstImg) {
    if (pSrcImg == nullptr || pDstImg->ppPlane[0] == nullptr) {
        LOG_E("NativeImageUtil::CopyNativeImage invalid pSrcImg");
        return;
    }

    if (pSrcImg->format != pDstImg->format
        || pSrcImg->width != pDstImg->width
        || pSrcImg->height != pDstImg->width) {
        LOG_E("NativeImageUtil::CopyNativeImage invalid format or width or height ");
        return;
    }

    switch (pSrcImg->format) {
        case IMAGE_FORMAT_I420:
            if (pSrcImg->pLineSize[0] != pDstImg->pLineSize[0]) { //yplane
                for (int i = 0; i < pSrcImg->height; ++i) {
                    memcpy(pDstImg->ppPlane[0] + i * pDstImg->pLineSize[0],
                           pSrcImg->ppPlane[0] + i * pSrcImg->pLineSize[0],
                           pDstImg->width
                    );
                }
            } else {
                memcpy(pDstImg->ppPlane[0],
                       pSrcImg->ppPlane[0],
                       pDstImg->pLineSize[0] * pSrcImg->height);
            }

            if (pSrcImg->pLineSize[1] != pDstImg->pLineSize[1]) {// u plane
                for (int i = 0; i < pSrcImg->height / 2; ++i) {
                    memcpy(pDstImg->ppPlane[1] + i * pDstImg->pLineSize[1],
                           pSrcImg->ppPlane[1] + i * pSrcImg->pLineSize[1],
                           pDstImg->width / 2
                    );
                }
            } else {
                memcpy(pDstImg->ppPlane[1],
                       pSrcImg->ppPlane[1],
                       pDstImg->pLineSize[1] * pSrcImg->height / 2);
            }

            if (pSrcImg->pLineSize[2] != pDstImg->pLineSize[2]) { // v plane
                for (int i = 0; i < pSrcImg->height / 2; ++i) {
                    memcpy(pDstImg->ppPlane[2] + i * pDstImg->pLineSize[2],
                           pSrcImg->ppPlane[2] + i * pSrcImg->pLineSize[2],
                           pDstImg->width / 2
                    );
                }
            } else {
                memcpy(pDstImg->ppPlane[2],
                       pSrcImg->ppPlane[2],
                       pDstImg->pLineSize[2] * pSrcImg->width / 2
                );
            }

            break;
        case IMAGE_FORMAT_NV12:
        case IMAGE_FORMAT_NV21:
            //  todo 待完善，必须完善
            break;
        case IMAGE_FORMAT_RGBA:
            //  todo     待完善，必须完善
            break;
    }

}
